﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace l1cs.server.utils
{
    /**
     * <p>
     * 最低値lowと最大値highによって囲まれた、数値の範囲を指定するクラス。
     * </p>
     * <p>
     * <b>このクラスは同期化されない。</b> 複数のスレッドが同時にこのクラスのインスタンスにアクセスし、
     * 1つ以上のスレッドが範囲を変更する場合、外部的な同期化が必要である。
     * </p>
     */
    public class IntRange
    {
        private Random _rnd = new Random();
        private int _low;
        private int _high;

        public IntRange( int low, int high )
        {
            _low = low;
            _high = high;
        }

        public IntRange( IntRange range )
            : this( range._low, range._high )
        {
        }

        /**
         * 数値iが、範囲内にあるかを返す。
         * 
         * @param i
         *            数値
         * @return 範囲内であればtrue
         */
        public bool includes( int i )
        {
            return ( _low <= i ) && ( i <= _high );
        }

        public static bool includes( int i, int low, int high )
        {
            return ( low <= i ) && ( i <= high );
        }

        /**
         * 数値iを、この範囲内に丸める。
         * 
         * @param i
         *            数値
         * @return 丸められた値
         */
        public int ensure( int i )
        {
            int r = i;
            r = ( _low <= r ) ? r : _low;
            r = ( r <= _high ) ? r : _high;
            return r;
        }

        public static int ensure( int n, int low, int high )
        {
            int r = n;
            r = ( low <= r ) ? r : low;
            r = ( r <= high ) ? r : high;
            return r;
        }

        /**
         * この範囲内からランダムな値を生成する。
         * 
         * @return 範囲内のランダムな値
         */
        public int randomValue()
        {
            return _rnd.Next( getWidth() + 1 ) + _low;
        }

        public int getLow()
        {
            return _low;
        }

        public int getHigh()
        {
            return _high;
        }

        public int getWidth()
        {
            return _high - _low;
        }

        //override
        public bool equals( Object obj )
        {
            if ( !( obj is IntRange ) )
            {
                return false;
            }
            IntRange range = (IntRange)obj;
            return ( this._low == range._low ) && ( this._high == range._high );
        }

        //override
        public String toString()
        {
            return "low=" + _low + ", high=" + _high;
        }
    }

}
